package com.ds.esd.formula.component;


import com.ds.common.JDSException;
import com.ds.context.JDSActionContext;
import com.ds.esd.client.ESDFacrory;
import com.ds.esd.custom.annotation.CustomAnnotation;
import com.ds.esd.custom.annotation.PopTreeAnnotation;
import com.ds.esd.custom.annotation.TreeAnnotation;
import com.ds.esd.custom.annotation.toolbar.BottomBarMenu;
import com.ds.esd.custom.form.enums.CustomFormMenu;
import com.ds.esd.formula.service.ComponentFService;
import com.ds.esd.tool.module.EUModule;
import com.ds.esd.tool.module.EUPackage;
import com.ds.esd.tool.ui.component.Component;
import com.ds.esd.tool.ui.component.Properties;
import com.ds.esd.tool.ui.component.UIItem;
import com.ds.esd.tool.ui.component.container.AbsUIProperties;
import com.ds.esd.tool.ui.component.item.GalleryItem;
import com.ds.esd.tool.ui.component.list.AbsListProperties;
import com.ds.esd.tool.ui.component.list.ListFieldProperties;
import com.ds.esd.tool.ui.component.list.TreeListItem;
import com.ds.esd.tool.ui.component.list.TreeListProperties;
import com.ds.esd.tool.ui.enums.ComponentType;
import com.ds.esd.tool.ui.enums.SelModeType;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@BottomBarMenu
@TreeAnnotation(heplBar = true, selMode = SelModeType.multibycheckbox, bottombarMenu = {CustomFormMenu.Close, CustomFormMenu.Save}, customService = {ComponentFService.class})
@PopTreeAnnotation(caption = "添加子对象")
public class ItemPopTree<T extends ItemPopTree> extends TreeListItem<T> {

    @CustomAnnotation(pid = true)
    String pattern = "";

    @CustomAnnotation(pid = true)
    String projectId;

    @CustomAnnotation(pid = true)
    String formulaInstId;

    @CustomAnnotation(pid = true)
    String parameterCode;

    @CustomAnnotation(pid = true)
    String paramsType;


    public ItemPopTree(String pattern, ComponentType... componentTypes) throws JDSException {
        super("allComponent", "所有组件");
        this.setIniFold(false);
        this.iniFold = false;
        this.imageClass = "spafont spa-icon-conf";
        String projectName = (String) JDSActionContext.getActionContext().getParams("projectName");
        List<EUPackage> packages = ESDFacrory.getESDClient().getAllPackage(projectName);
        for (EUPackage euPackage : packages) {
            this.addChild((T) new ItemPopTree(pattern, euPackage, componentTypes));
        }
    }


    public ItemPopTree(String pattern, EUPackage euPackage, ComponentType... componentTypes) throws JDSException {
        super(euPackage.getPackageName(), euPackage.getPackageName());
        this.imageClass = "fa fa-cubes";
        this.iniFold = false;

        for (EUModule euModule : euPackage.listModules()) {
            this.addChild((T) new ItemPopTree(pattern, euModule, componentTypes));
        }
    }

    public ItemPopTree(String pattern, EUModule euModule, ComponentType... componentTypes) throws JDSException {
        super(euModule.getClassName(), euModule.getName());
        this.imageClass = "spafont spa-icon-page";
        List<Component> componentList = new ArrayList<>();
        if (euModule.getComponent().getChildren() != null) {
            componentList.addAll(euModule.getComponent().getChildren());
            for (Component childComponent : componentList) {
                if (hasChild(pattern, childComponent, componentTypes)) {
                    this.addChild((T) new ItemPopTree(pattern, childComponent, componentTypes));
                }
            }
        }

    }

    public ItemPopTree(String pattern, Component component, ComponentType... componentTypes) throws JDSException {
        super(component.getPath(), component.getAlias() + "(" + component.getProperties().getDesc() + ")");
        ComponentType componentType = ComponentType.fromType(component.getKey());
        this.imageClass = componentType.getImageClass();
        this.addTagVar("euClassName", component.getModuleComponent().getClassName());
        this.caption = component.getAlias() + "(" + componentType.name() + ")";
        List<Component> componentList = new ArrayList<>();
        if (component.getChildren() != null) {
            componentList.addAll(component.getChildren());
            for (Component childComponent : componentList) {
                if (hasChild(pattern, childComponent, componentTypes)) {
                    this.addChild((T) new ItemPopTree(pattern, childComponent, componentTypes));
                }

            }
        } else if (component.getProperties() instanceof TreeListProperties) {
            TreeListProperties properties = (TreeListProperties) component.getProperties();
            if (pattern(pattern, (properties).getChildrenRecursivelyList())) {
                List<TreeListItem> listItems = properties.getItems();
                for (TreeListItem item : listItems) {
                    this.addChild((T) new ItemPopTree(pattern, item));
                }

            }
        } else if (component.getProperties() instanceof AbsListProperties) {
            AbsListProperties properties = (AbsListProperties) component.getProperties();
            if (pattern(pattern, (properties).getItems())) {
                List<TreeListItem> listItems = properties.getItems();
                for (AbsUIProperties item : listItems) {
                    this.addChild((T) new ItemPopTree(pattern, item));
                }

            }
        } else if (component.getProperties() instanceof ListFieldProperties) {
            ListFieldProperties properties = (ListFieldProperties) component.getProperties();
            if (pattern(pattern, (properties).getItems())) {
                List<UIItem> listItems = properties.getItems();
                for (UIItem item : listItems) {
                    this.addChild((T) new ItemPopTree(pattern, item));
                }

            }
        }


    }

    public ItemPopTree(String pattern, GalleryItem listItem) {
        super(listItem.getId(), listItem.getId() + "(" + listItem.getCaption() + ")");
        this.imageClass = listItem.getImageClass();
        if (listItem.getComment() != null && listItem.getComment().equals("")) {
            this.caption = listItem.getComment() + "(" + listItem.getCaption() + ")";
        } else {
            this.caption = listItem.getCaption();
        }

    }

    public ItemPopTree(String pattern, AbsUIProperties listItem) {
        super(listItem.getId(), listItem.getId() + "(" + listItem.getCaption() + ")");
        this.imageClass = listItem.getImageClass();
        this.caption = listItem.getCaption();

    }

    public ItemPopTree(String pattern, ListFieldProperties listItem) {
        super(listItem.getId(), listItem.getId() + "(" + listItem.getCaption() + ")");
        this.imageClass = listItem.getImageClass();
        this.caption = listItem.getCaption();

    }

    public ItemPopTree(String pattern, TreeListItem<TreeListItem> listItem) {
        super(listItem.getId(), listItem.getId() + "(" + listItem.getCaption() + ")");
        this.imageClass = listItem.getImageClass();
        this.caption = listItem.getCaption();

        if (listItem != null) {
            for (UIItem sub : listItem.getSub()) {
                this.addChild((T) new ItemPopTree(pattern, sub));
            }
        }

    }


    private boolean checkChild(String pattern, Component component) {
        List<Component> components = component.getChildrenRecursivelyList();
        if (pattern(pattern, component)) {
            return true;
        }
        for (Component childComponent : components) {
            if (pattern(pattern, childComponent)) {
                return true;
            }
        }
        return false;
    }

    private boolean pattern(String pattern, Component component) {
        Properties properties = component.getProperties();
        if (properties instanceof TreeListProperties) {
            return pattern(pattern, ((TreeListProperties) properties).getChildrenRecursivelyList());
        }

        if (properties instanceof AbsListProperties) {
            return pattern(pattern, ((AbsListProperties) properties).getItems());
        }


        if (properties instanceof ListFieldProperties) {
            return pattern(pattern, ((ListFieldProperties) properties).getItems());
        }


        return false;
    }

    private boolean pattern(String pattern, List<UIItem> items) {
        if (items != null) {
            for (UIItem item : items) {
                if (pattern != null && !pattern.equals("")) {
                    Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
                    Matcher namematcher = p.matcher(item.getName());
                    Matcher descmatcher = p.matcher(item.getDesc());

                    if (namematcher.find() || descmatcher.find()) {
                        return true;
                    }
                } else {
                    return true;
                }
            }
        }

        return false;

    }


    boolean hasChild(String pattern, Component component, ComponentType... componentTypes) {


        if ((componentTypes == null || componentTypes.length == 0) && pattern(pattern, component)) {
            return true;
        }
        Set<ComponentType> types = new LinkedHashSet<>();
        List<Component> componentList = new ArrayList<>();
        componentList.addAll(component.getChildrenRecursivelyList());


        for (ComponentType componentType : componentTypes) {
            if (componentType.equals(component.typeKey) && pattern(pattern, component)) {
                return true;
            }
        }

        for (Component childComponent : componentList) {
            types.add(childComponent.typeKey);
        }
        return checkIn(types, componentTypes);
    }


    boolean checkIn(Set<ComponentType> types, ComponentType... componentTypes) {
        if (componentTypes == null || componentTypes.length == 0) {
            return true;
        }
        for (ComponentType componentType : componentTypes) {
            if (componentType != null && types.contains(componentType)) {
                return true;
            }
        }
        return false;
    }

    public String getProjectId() {
        return projectId;
    }

    public void setProjectId(String projectId) {
        this.projectId = projectId;
    }

    public String getFormulaInstId() {
        return formulaInstId;
    }

    public void setFormulaInstId(String formulaInstId) {
        this.formulaInstId = formulaInstId;
    }

    public String getParameterCode() {
        return parameterCode;
    }

    public void setParameterCode(String parameterCode) {
        this.parameterCode = parameterCode;
    }

    public String getParamsType() {
        return paramsType;
    }

    public void setParamsType(String paramsType) {
        this.paramsType = paramsType;
    }

    public String getPattern() {
        return pattern;
    }

    public void setPattern(String pattern) {
        this.pattern = pattern;
    }

}
